package com.yyy.dm.consumer.service;

import com.yyy.dm.CommonResponse;
import com.yyy.dm.SnowFlakeUtil;
import com.yyy.dm.VoUtil;
import com.yyy.dm.consumer.feign.item.DMItemFeign;
import com.yyy.dm.consumer.feign.scheduler.DMSchedulerSeatFeign;
import com.yyy.dm.consumer.feign.scheduler.DMSchedulerSeatPriceFeign;
import com.yyy.dm.consumer.feign.user.DMLinkUserFeign;
import com.yyy.dm.dao.OrderLinkUserMapper;
import com.yyy.dm.dao.OrderMapper;
import com.yyy.dm.order.DMOrder;
import com.yyy.dm.order.DMOrderLinkUser;
import com.yyy.dm.order.FindOrderDTO;
import com.yyy.dm.order.PayOrderDTO;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OrderConsumerService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private DMSchedulerSeatPriceFeign dmSchedulerSeatPriceFeign;
    @Resource
    private DMItemFeign dmItemFeign;
    @Resource
    private DMSchedulerSeatFeign dmSchedulerSeatFeign;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private DMLinkUserFeign dmLinkUserFeign;
    @Resource
    private OrderLinkUserMapper orderLinkUserMapper;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private Redisson redisson;

    public static final String LOCK_PREFIX = "redis_lock";

    public CommonResponse submitOrder(Map<String, String> map) {
        //分布式锁 （最后加）
        RLock rLock = redisson.getLock(LOCK_PREFIX+map.get("schedulerId"));
//        while (!redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX+map.get("schedulerId"), uuid, 5, TimeUnit.SECONDS)) {
//
//        }
        DMOrder dmOrder;
        try {
            rLock.lock();
            String itemName = dmItemFeign.findItemNameById(Long.parseLong(map.get("itemId")));
            String seatPositions = map.get("seatPositions");
            String[] seats = seatPositions.split(","); //1_2,3_4    seats[0] = 1_2  3_4
            Double totalAmount = 0.0;
            Integer totalCount = seats.length;
            Double[] prices = new Double[seats.length];
            List<HashMap> schedulerSeatList = new ArrayList<>();
            for (int i = 0; i < seats.length; i++) {
                String[] xy = seats[i].split("_");
                String x = xy[0];
                String y = xy[1];
                HashMap hashMap = new HashMap() {{
                    put("x", x);
                    put("y", y);
                    put("schedulerId", map.get("schedulerId"));
                }};
                Double price = dmSchedulerSeatPriceFeign.findSchedulerSeatPriceByScheduleIdAndXY(hashMap);
                prices[i] = price;
                totalAmount += price;
                //算价格的同时修改座位状态
                //            Integer result = dmSchedulerSeatFeign.updateSchedulerSeat(hashMap);
                //循环查看座位是否还在  不在直接抛异常
                Integer result = dmSchedulerSeatFeign.findSchedulerSeatStatusByScheduleIdAndXY(hashMap);
                if (result != 1) {
                    throw new RuntimeException("请选择其他座位");
                }
                schedulerSeatList.add(hashMap);
            }
            dmOrder = new DMOrder();
            dmOrder.setOrderNo(SnowFlakeUtil.getId().toString());
            dmOrder.setUserId(Long.parseLong(map.get("userId")));
            dmOrder.setSchedulerId(Long.parseLong(map.get("schedulerId")));
            dmOrder.setItemId(Long.parseLong(map.get("itemId")));
            dmOrder.setItemName(itemName);
            dmOrder.setOrderType(0);
            dmOrder.setTotalCount(totalCount);
            dmOrder.setSourceType(Integer.parseInt(map.get("sourceType")));
            dmOrder.setIsNeedInvoice(Integer.parseInt(map.get("isNeedInvoice")));
            dmOrder.setInvoiceHead(map.get("invoiceHead"));
            dmOrder.setInvoiceNo(map.get("invoiceNo"));
            dmOrder.setInvoiceType(Integer.parseInt(map.get("invoiceType")));
            dmOrder.setTotalAmount(totalAmount);
            Integer isNeedInsurance = Integer.parseInt(map.get("isNeedInsurance"));
            dmOrder.setIsNeedInsurance(isNeedInsurance);
            if (isNeedInsurance == 0)
                dmOrder.setInsuranceAmount(0.0);
            else
                dmOrder.setInsuranceAmount(20.0);
            dmOrder.setCreatedTime(LocalDateTime.now());
            dmOrder.setUpdatedTime(LocalDateTime.now());


            //分布式事务
            //添加订单 第一个添加异常 没有任何记录修改 不用回滚
            orderMapper.insert(dmOrder);
            //修改座位状态 第二个异常 是循环 回滚第一个和第二个
            try {
                for (HashMap hashMap : schedulerSeatList) {
                    hashMap.put("orderNo", dmOrder.getOrderNo());
                    hashMap.put("userId", map.get("userId"));
                    dmSchedulerSeatFeign.updateSchedulerSeat(hashMap);
                }
            } catch (Exception e) {
                rabbitTemplate.convertAndSend("dm_exchange", "order_router", dmOrder.getId());
                rabbitTemplate.convertAndSend("dm_exchange", "scheduler_seat_router", dmOrder.getOrderNo());
                throw new RuntimeException();
            }
            //添加订单联系人
            try {
                String linkIds = map.get("linkIds");
                String[] linkIdArr = linkIds.split(",");
                for (int i = 0; i < linkIdArr.length; i++) {
                    String linkId = linkIdArr[i];
                    String linkUserName = dmLinkUserFeign.findLinkUserNameById(Long.parseLong(linkId));
                    //循环查名字 取 prices 的值 添加
                    String[] xy = seats[i].split("_");
                    String x = xy[0];
                    String y = xy[1];
                    Double price = prices[i];
                    DMOrderLinkUser dmOrderLinkUser = new DMOrderLinkUser();
                    dmOrderLinkUser.setOrderId(dmOrder.getId());
                    dmOrderLinkUser.setLinkUserId(Long.parseLong(linkId));
                    dmOrderLinkUser.setLinkUserName(linkUserName);
                    dmOrderLinkUser.setX(Integer.parseInt(x));
                    dmOrderLinkUser.setY(Integer.parseInt(y));
                    dmOrderLinkUser.setPrice(price);
                    dmOrderLinkUser.setCreatedTime(LocalDateTime.now());
                    dmOrderLinkUser.setUpdatedTime(LocalDateTime.now());
                    orderLinkUserMapper.insert(dmOrderLinkUser);
                    rabbitTemplate.convertAndSend("dm_order_exchange","dm.order",dmOrder,message -> {
                        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                        message.getMessageProperties().setExpiration(3*60*1000+"");
                        return message;
                    });
                }
            } catch (Exception e) {
                rabbitTemplate.convertAndSend("dm_exchange", "order_router", dmOrder.getId());
                rabbitTemplate.convertAndSend("dm_exchange", "scheduler_seat_router", dmOrder.getOrderNo());
                rabbitTemplate.convertAndSend("dm_exchange", "order_link_user_router", dmOrder.getId());
                e.printStackTrace();
                throw new RuntimeException("添加订单联系人异常");
            }
        } finally {
            rLock.unlock();
//            String lock = redisTemplate.opsForValue().get(LOCK_PREFIX+map.get("schedulerId"));
//            if (uuid.equals(lock)) {
//                redisTemplate.delete(LOCK_PREFIX);
//            } else {
//                throw new RuntimeException("锁不一致");
//            }
        }
        return VoUtil.returnSuccess(new HashMap() {{
            put("orderNo", dmOrder.getOrderNo());
        }});
    }



    public CommonResponse queryOrderList(Map<String, String> map) {
        List<FindOrderDTO> findOrderDTOList = orderMapper.findOrderListConditional(map);
        return VoUtil.returnSuccess(findOrderDTOList);
    }

    public CommonResponse confirmPay(String orderNo) {
        PayOrderDTO payOrderDTO = orderMapper.findPayOrderByOrderNo(orderNo);
        return VoUtil.returnSuccess(payOrderDTO);
    }


}
